home *** CD-ROM | disk | FTP | other *** search
/ Aminet 30 / Aminet 30 (1999)(Schatztruhe)[!][Apr 1999].iso / Aminet / dev / lang / SmallEiffel.lha / SmallEiffel / lib_se / switch.e < prev    next >
Text File  |  1998-12-22  |  11KB  |  453 lines

  1. --          This file is part of SmallEiffel The GNU Eiffel Compiler.
  2. --          Copyright (C) 1994-98 LORIA - UHP - CRIN - INRIA - FRANCE
  3. --            Dominique COLNET and Suzanne COLLIN - colnet@loria.fr 
  4. --                       http://www.loria.fr/SmallEiffel
  5. -- SmallEiffel is  free  software;  you can  redistribute it and/or modify it 
  6. -- under the terms of the GNU General Public License as published by the Free
  7. -- Software  Foundation;  either  version  2, or (at your option)  any  later 
  8. -- version. SmallEiffel is distributed in the hope that it will be useful,but
  9. -- WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
  10. -- or  FITNESS FOR A PARTICULAR PURPOSE.   See the GNU General Public License 
  11. -- for  more  details.  You  should  have  received a copy of the GNU General 
  12. -- Public  License  along  with  SmallEiffel;  see the file COPYING.  If not,
  13. -- write to the  Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  14. -- Boston, MA 02111-1307, USA.
  15. --
  16. expanded class SWITCH
  17.    --
  18.    -- Set of tools (no attributes) to handle one switching site.
  19.    --
  20.  
  21. inherit GLOBALS;
  22.  
  23. feature {NONE}
  24.  
  25.    running: ARRAY[RUN_CLASS] is
  26.      -- The global one.
  27.       once
  28.      !!Result.with_capacity(256,1);
  29.       end;
  30.    
  31. feature 
  32.    
  33.    c_define(up_rf: RUN_FEATURE) is
  34.      -- Define the switching C function for `up_rf'.
  35.       require
  36.      cpp.on_c
  37.       local
  38.      boost: BOOLEAN;
  39.      arguments:  FORMAL_ARG_LIST;
  40.      result_type, arg_type: TYPE;
  41.      i: INTEGER;
  42.       do
  43.      boost := run_control.boost;
  44.      arguments := up_rf.arguments;
  45.      result_type := up_rf.result_type;
  46.      c_code.clear;
  47.      if result_type = Void then
  48.         c_code.append(fz_void);
  49.      else
  50.         result_type := result_type.run_type;
  51.         result_type.c_type_for_result_in(c_code);
  52.      end;
  53.      c_code.extend(' ');
  54.      c_code.extend('X');
  55.      up_rf.current_type.id.append_in(c_code);
  56.      up_rf.name.mapping_c_in(c_code);
  57.      if boost then
  58.         c_code.append("(void *C");
  59.      else
  60.         c_code.append("(se_dump_stack*caller,int l,int c,int f, void *C");
  61.      end;
  62.      if arguments /= Void then
  63.         from  
  64.            i := 1;
  65.         until
  66.            i > arguments.count
  67.         loop
  68.            c_code.extend(',');
  69.            arg_type := arguments.type(i).run_type;
  70.            arg_type.c_type_for_argument_in(c_code);
  71.            c_code.append(" a");
  72.            i.append_in(c_code);
  73.            i := i + 1;
  74.         end;
  75.      end;
  76.      c_code.extend(')');
  77.      cpp.put_c_heading(c_code);
  78.      cpp.swap_on_c;
  79.      if result_type /= Void then
  80.         c_code.clear;
  81.         result_type.c_type_for_result_in(c_code);
  82.         c_code.extend(' ');
  83.         c_code.extend('R');
  84.         if not boost then
  85.            c_code.extend('=');
  86.            result_type.c_initialize_in(c_code);
  87.         end;
  88.         c_code.append(fz_00);
  89.         cpp.put_string(c_code);
  90.      end;
  91.      if not boost then
  92.         cpp.put_string("se_dump_stack ds=*caller;%N");
  93.      end;
  94.      cpp.put_string("{int id=");
  95.      running.copy(up_rf.current_type.run_class.running);
  96.      sort_running(running);
  97.      if boost then
  98.         cpp.put_string("((T0*)C)->id;%N");
  99.      else
  100.         cpp.put_string("vc(C,l,c,f)->id;%N");
  101.      end;
  102.      if run_control.all_check then
  103.         c_switch(up_rf);
  104.      else
  105.         c_dicho(up_rf,1,running.upper);
  106.      end;
  107.      cpp.put_string(fz_12);
  108.      if not boost then
  109.         cpp.put_string("se_dst=caller;%N");
  110.      end;
  111.      if result_type /= Void then
  112.         cpp.put_string(fz_15);
  113.      else
  114.         cpp.put_string(fz_12);
  115.      end;
  116.       ensure     
  117.      cpp.on_c
  118.       end;
  119.  
  120. feature {C_PRETTY_PRINTER}
  121.  
  122.    put_arguments(up_rf: RUN_FEATURE; fal: FORMAL_ARG_LIST) is
  123.      -- Produce C code for arguments of `fal' used
  124.      -- inside the switching C function.
  125.       require
  126.      cpp.on_c;
  127.      fal.count = up_rf.arguments.count
  128.       local
  129.      i, up: INTEGER;
  130.       do
  131.      from  
  132.         i := 1;
  133.         up := fal.count;
  134.      until
  135.         i > up
  136.      loop
  137.         if i > 1 then
  138.            cpp.put_character(',');
  139.         end;
  140.         put_ith_argument(up_rf,fal,i);
  141.         i := i + 1;
  142.      end;
  143.       ensure
  144.      cpp.on_c
  145.       end;
  146.    
  147.    put_ith_argument(up_rf: RUN_FEATURE; fal: FORMAL_ARG_LIST; index: INTEGER) is
  148.      -- Produce C code for argument `index' of `fal' used
  149.      -- inside the switching C function.
  150.       require
  151.      cpp.on_c;
  152.      fal.count = up_rf.arguments.count;
  153.      1 <= index;
  154.      index <= fal.count
  155.       local
  156.      eal: like fal;
  157.      at, ft: TYPE;
  158.       do
  159.      eal := up_rf.arguments;
  160.      at := eal.type(index).run_type;
  161.      ft := fal.type(index).run_type;
  162.      if at.is_reference and then ft.is_basic_eiffel_expanded then
  163.         cpp.put_character('(');
  164.         ft.cast_to_ref;
  165.         cpp.put_character('a');
  166.         cpp.put_integer(index);
  167.         cpp.put_string(")->_item");
  168.      else
  169.         cpp.put_character('a');
  170.         cpp.put_integer(index);
  171.      end;
  172.       ensure
  173.      cpp.on_c
  174.       end;
  175.    
  176. feature {NONE}
  177.    
  178.    c_dicho(up_rf: RUN_FEATURE; bi, bs: INTEGER) is
  179.      -- Produce dichotomic inspection code for Current id.
  180.       require
  181.      bi <= bs
  182.       local
  183.      m: INTEGER;
  184.      dyn_rc: RUN_CLASS;
  185.      dyn_rf: RUN_FEATURE;
  186.       do
  187.      if bi = bs then
  188.         dyn_rc := running.item(bi);
  189.         dyn_rf := dyn_rc.dynamic(up_rf);
  190.         tail_opening(up_rf.result_type,dyn_rf.result_type);
  191.         cpp.push_switch(dyn_rf,up_rf);
  192.         dyn_rf.mapping_c;
  193.         cpp.pop;
  194.         tail_closing(up_rf.result_type,dyn_rf.result_type);
  195.      else        
  196.         m := (bi + bs) // 2;
  197.         dyn_rc := running.item(m);
  198.         cpp.put_string("if(id<=");
  199.         cpp.put_integer(dyn_rc.id);
  200.         cpp.put_string("){%N");
  201.         c_dicho(up_rf,bi,m);
  202.         cpp.put_string("}%Nelse{%N");
  203.         c_dicho(up_rf,m + 1,bs);
  204.         cpp.put_character('}');
  205.      end;
  206.       end;
  207.  
  208.    c_switch(up_rf: RUN_FEATURE) is
  209.      -- Produce C switch inspection code for Current id.
  210.       local
  211.      i: INTEGER;
  212.      dyn_rc: RUN_CLASS;
  213.      dyn_rf: RUN_FEATURE;
  214.       do
  215.      cpp.put_string("switch(id){%N"); 
  216.      from
  217.         i := 1;
  218.      until
  219.         i > running.upper
  220.      loop
  221.         dyn_rc := running.item(i);
  222.         dyn_rf := dyn_rc.dynamic(up_rf);
  223.         cpp.put_string("case "); 
  224.         cpp.put_integer(dyn_rc.id);
  225.         cpp.put_character(':');
  226.         tail_opening(up_rf.result_type,dyn_rf.result_type);
  227.         cpp.push_switch(dyn_rf,up_rf);
  228.         dyn_rf.mapping_c;
  229.         cpp.pop;
  230.         tail_closing(up_rf.result_type,dyn_rf.result_type);
  231.         cpp.put_string("%Nbreak;%N"); 
  232.         i := i + 1;
  233.      end;
  234.      if run_control.no_check then
  235.         cpp.put_string("default: error2(C,l,c,f);%N");
  236.      end;
  237.      cpp.put_string(fz_12);
  238.       end;
  239.  
  240. feature {C_PRETTY_PRINTER,SWITCH}
  241.  
  242.    name(up_rf: RUN_FEATURE): STRING is
  243.       do
  244.      c_code.clear;
  245.      c_code.extend('X');
  246.      up_rf.current_type.id.append_in(c_code);
  247.      c_code.append(up_rf.name.to_key);
  248.      Result := c_code;
  249.       end;
  250.  
  251. feature
  252.  
  253.    jvm_descriptor(up_rf: RUN_FEATURE): STRING is
  254.       local
  255.      arguments:  FORMAL_ARG_LIST;
  256.      rt: TYPE;
  257.       do
  258.      arguments := up_rf.arguments;
  259.      tmp_jvmd.clear;
  260.      tmp_jvmd.extend('(');
  261.      tmp_jvmd.append(jvm_root_descriptor);
  262.      if arguments /= Void then
  263.         arguments.jvm_descriptor_in(tmp_jvmd);
  264.      end;
  265.      rt := up_rf.result_type;
  266.      if rt = Void then
  267.         tmp_jvmd.append(fz_19);
  268.      else
  269.         rt := rt.run_type;
  270.         tmp_jvmd.extend(')');
  271.         if rt.is_reference then
  272.            tmp_jvmd.append(jvm_root_descriptor);
  273.         else
  274.            rt.jvm_descriptor_in(tmp_jvmd);
  275.         end;
  276.      end;
  277.      Result := tmp_jvmd;
  278.       end;
  279.  
  280. feature {NONE}
  281.  
  282.    tmp_jvmd: STRING is
  283.       once
  284.      !!Result.make(32);
  285.       end;
  286.  
  287. feature 
  288.  
  289.    idx_methodref(up_rf: RUN_FEATURE): INTEGER is
  290.       require
  291.      up_rf /= Void
  292.       do
  293.      Result := constant_pool.idx_methodref3(jvm_root_class,
  294.                         name(up_rf),
  295.                         jvm_descriptor(up_rf));
  296.       end;
  297.    
  298. feature {JVM}
  299.  
  300.    jvm_mapping(cpc: CALL_PROC_CALL) is
  301.       require
  302.      cpc /= Void
  303.       local
  304.      idx, stack_level: INTEGER;
  305.      up_rf: RUN_FEATURE;
  306.      target: EXPRESSION;
  307.      eal: EFFECTIVE_ARG_LIST;
  308.      fal: FORMAL_ARG_LIST;
  309.      switch: SWITCH;
  310.       do
  311.      target := cpc.target;
  312.      up_rf := cpc.run_feature;
  313.      eal := cpc.arguments;
  314.      target.compile_to_jvm;
  315.      stack_level := 1;
  316.      if eal /= Void then
  317.         fal := up_rf.arguments;
  318.         stack_level := stack_level + eal.compile_to_jvm(fal);
  319.      end;
  320.      if up_rf.result_type /= Void then
  321.         stack_level := stack_level - up_rf.result_type.jvm_stack_space;
  322.      end;
  323.      idx := switch.idx_methodref(up_rf);
  324.      code_attribute.opcode_invokestatic(idx,-stack_level);
  325.       end;
  326.  
  327. feature {SWITCH_COLLECTION}
  328.  
  329.    jvm_define(up_rf: RUN_FEATURE) is
  330.       local
  331.      rt: TYPE;
  332.       do
  333.      -- Define the Java switching static method for `up_rf'.
  334.      method_info.start(9,name(up_rf),jvm_descriptor(up_rf));
  335.      running.copy(up_rf.current_type.run_class.running);
  336.      rt := up_rf.result_type;
  337.      if rt /= Void then
  338.         rt := rt.run_type;
  339.      end;
  340.      jvm_switch(up_rf,rt);
  341.      method_info.finish;
  342.       end;
  343.  
  344. feature {NONE}
  345.  
  346.    c_code: STRING is
  347.       once
  348.      !!Result.make(256);
  349.       end;
  350.  
  351.    tail_opening(x_type, r_type: TYPE) is
  352.       do
  353.      if x_type /= Void then
  354.         c_code.copy("R=((");
  355.         x_type.c_type_for_result_in(c_code);
  356.         c_code.append(")(");
  357.         cpp.put_string(c_code);
  358.         if r_type.is_expanded and then x_type.is_reference then
  359.            r_type.to_reference;
  360.            cpp.put_character('(');
  361.         end;
  362.      end;
  363.       end;
  364.  
  365.    tail_closing(x_type, r_type: TYPE) is
  366.       do
  367.      if x_type /= Void then
  368.         if r_type.is_expanded and then x_type.is_reference then
  369.            cpp.put_character(')');
  370.         end;
  371.         cpp.put_string(fz_16);
  372.      end;
  373.       end;
  374.  
  375. feature {NONE}
  376.  
  377.    jvm_switch(up_rf: RUN_FEATURE; rt: TYPE) is
  378.      -- Produce Java sequential switch code.
  379.       require
  380.      rt /= Void implies rt.run_type = rt
  381.       local
  382.      space, point, i: INTEGER;
  383.      dyn_rc: RUN_CLASS;
  384.      dyn_rf: RUN_FEATURE;
  385.      boost: BOOLEAN;
  386.      ca: like code_attribute;
  387.      static_na, dynamic_na: TYPE_NATIVE_ARRAY;
  388.       do
  389.      ca := code_attribute;
  390.      from
  391.         boost := run_control.boost;
  392.         i := running.upper;
  393.      until
  394.         i = 0
  395.      loop
  396.         dyn_rc := running.item(i);
  397.         dyn_rf := dyn_rc.dynamic(up_rf);
  398.         if i = 1 and then boost then
  399.         else
  400.            ca.opcode_aload_0;
  401.            dyn_rf.run_class.opcode_instanceof;
  402.            point := ca.opcode_ifeq;
  403.         end;
  404.         jvm.push_switch(dyn_rf,up_rf);
  405.         dyn_rf.mapping_jvm;
  406.         jvm.pop;
  407.         if rt = Void then 
  408.            ca.opcode_return;
  409.         elseif rt.is_native_array then
  410.            static_na ?= rt.run_type;
  411.            dynamic_na ?= dyn_rf.result_type.run_type;
  412.            if static_na.run_time_mark = dynamic_na.run_time_mark then
  413.           static_na.jvm_return_code;
  414.            elseif static_na.of_references and then dynamic_na.of_references then
  415.           static_na.jvm_return_code;
  416.            else
  417.           if run_control.no_check then
  418.              ca.runtime_error(up_rf.start_position,up_rf.current_type,
  419.                      "System-level Validity error detected inside virtual %
  420.              %switching code.%N%
  421.              %Bad NATIVE_ARRAY type return type.");
  422.           end;
  423.           ca.opcode_pop;
  424.           space := rt.jvm_push_default;
  425.           rt.jvm_return_code;
  426.            end;
  427.         else
  428.            space := dyn_rf.result_type.jvm_convert_to(rt);
  429.            rt.jvm_return_code;
  430.         end;
  431.         if i = 1 and then boost then
  432.         else
  433.            ca.resolve_u2_branch(point);
  434.         end;
  435.         i := i - 1;
  436.      end;
  437.      if not boost then
  438.         ca.opcode_aload_0;
  439.         ca.runtime_error_bad_target(up_rf.start_position,up_rf.current_type,
  440.                "System-level Validity error detected inside virtual %
  441.            %switching code.%N%
  442.                %Bad target type for dynamic dispatch.");
  443.         if rt = Void then
  444.            ca.opcode_return;
  445.         else
  446.            space := rt.jvm_push_default;
  447.            rt.jvm_return_code;
  448.         end;
  449.      end;
  450.       end;
  451.  
  452. end
  453.